﻿(function(){
	$.fn.enableContextMenu = function(enable){
		var op = this.data("contextMenuOp");
		op._stop = !enable;
	}
	
	$.fn.contextMenu = function(op){
		op = $.extend({
			menus:null,
			target:null,
			container:null, //触发按钮容器
			panelBegin : "<ul>",
			item : "<li class='ccay-contextmen-item ${css}' ${click}>${#text}${#children}</li>",
			panelEnd : "</ul>",
			fixed:null,
			offset:true,	//是否采用绝对定位
			fnHover:null,
			fnGetData:null,
			fnCallMenu:null,
			selectClose:null,
			setBorder:true //是否需要边框
		},op);
		
		// 复制
		if (op.menus) {
			op.menus = Ccay.DataHelper.copyArray(op.menus);
		}
		
		if(op.mode == "click"){
			initClickModel(op,this);
			this.data("contextMenuOp",op);
			return;
		}
		
		var id =  $.newGuid('cm_'),
			selector = contextMenu.buildList(this,op,id),
			cMenu = contextMenu.buildTrigger(this,op,id,selector),
			fnHover = function(e){
				if(op._stop)
					return;
				var target = $.getEventTarget(e,function(dom){
					return dom.hasClass(op.target);
				});

				if(target.hasClass(op.target))
				{
					if(!target.data('cm_active'))
					{
						if(!op.fnHover || op.fnHover(target,cMenu) !== false){
							var height = target.outerHeight(),
								fixed = {left:target.outerWidth() - cMenu.outerWidth(),top:-1},
								targetPos = target.offset();

							// 自定义target
							op.fnGetTarget && (target = op.fnGetTarget(target,cMenu,fixed,op));
							//判断鼠标位置是否在对象区域类，主要处理滚动后的触发对象延迟的问题
							if(e.pageY >= targetPos.top && e.pageY <= targetPos.top + height){
								//修正相对域环境的位置
								if(op.fixed)
								{
									var fixPos = $(target).fixedPosition();
									fixed.left += fixPos.left;
									fixed.top += fixPos.top;
								}
								target.addClass("ccay-contextmenu-active");

								var oldTarget = cMenu.data('target');
								oldTarget && oldTarget.removeData("cm_active").removeClass("ccay-contextmenu-active");
								target.data('cm_active',1);
								cMenu.data('target',target).children('.ccay-contextmenu-hover').css({height:height,'line-height':(height+2)+'px'});
								// popup
								Ccay.UI.popup(target,cMenu,fixed,true,op.offset);
								op.setBorder && contextMenu.popupBorder(target,op,cMenu);
								//op.hoverCss && target.addClass(op.hoverCss);
								if(!op._lastTarget || op._lastTarget[0] != target[0])
								{
									op._lastTarget = target;
									selector.hide();
								}
							}else{
								cMenu.hide();
								selector.hide();
							}
						}
					}
				}
				else 
				if(!target.hasClass('ccay-contextmenu-trigger') && !target.hasClass('ccay-contextmenu-list') && !target.parent().hasClass('ccay-contextmen-item'))
				{
					var p = target.parent();
					if(!p.hasClass('ccay-contextmenu-trigger') && !p.hasClass('ccay-contextmenu-list')){
						contextMenu.close(cMenu,selector,op);
					}
						
				}
			},
			fnHoverEnd = function(e){
				if(op._stop)
					return;
				contextMenu.close(cMenu,selector,op);
			};
		if(op.target){
			this.bind("mouseover._contextmenu",fnHover).bind("mouseleave._contextmenu",fnHoverEnd);
		}
		this.data("contextMenuOp",op);

		return this;
	}
	
	var initClickModel = function(op,dom){
		var id =  $.newGuid('cm_'), 
			selector = contextMenu.buildList(dom,op,id).attr("tabIndex",-1).focusout(function(e){
				// 菜单中的input无焦点时关闭 add by l00195395 
				var	me = $(this);
				// 第一个timeout是使chrome可正确判断焦点
				// 第二个timeout时防止下拉菜单项点击不到
				setTimeout(function(){
					// 是否有可见的弹出下拉框
					var hasPop = $(".ccay-popup.ccay-selector:visible, .ccay-popup.ccay-calendar:visible").length > 0 ;
					if(me.is(":focus") || me.find(":focus").length > 0  || (hasPop && me.find("input").length) || $(document.activeElement).hasClass("ccay-contextmenu-list")){
						// 有可见的弹出下拉框时，输入框聚焦
						if(hasPop){
							var dropdown = me.find(".ccay-dropdown");
							dropdown.length && dropdown.focus();
						}
						op.selectClose = false;
					}else{
						op.selectClose = true;
					}
					//setTimeout(function(){
						op.selectClose &&  me.hide();
					//},150);
				},150)
		});
		var cMenu = $.create('div','ccay-contextmenu',id);
		dom.delegate(op.target,"click",function(e){
			var target =$(this),data;
			cMenu.data("target",target)	;
			data = op.fnGetData ? op.fnGetData(target) : null;

			if(!op.fnCallMenu || op.fnCallMenu(target,cMenu,selector,data) !== false){
				//自定义模式
				if(op.fnCustomMenu)
				{
					if(op.fnCustomMenu(target,selector,op,data,contextMenu))
						return false;
				}
				//动态创建模式
				if(op.fnDynamicMenu)
				{
					var menus = op.fnDynamicMenu(target,op,data,e);
					if(menus)
					{
						contextMenu.buildItems(selector,menus,op,true);
					}
				}
				else
					contextMenu.checkList(target,selector,op,data);
					 
				if(!menus)
					return;
				Ccay.UI.popup(this,selector,{top : target.outerHeight(),left :  target.outerWidth() - selector.outerWidth()});
				if(op.fixPanel && target.parents(op.fixPanel).length > 0){
					var fixPanel = target.parents(op.fixPanel);
					if(selector.position().left + selector.outerWidth() > fixPanel.width()){
						selector.css({left :  fixPanel.width() -  selector.outerWidth()});
					}
				}
				selector.focus();
				//回调方法
				op.callback && op.callback.call(this,target,selector,op);
			}
		});
		cMenu.appendTo(op.container || dom);
		// 是否buildBorder添加边框
		op.setBorder && contextMenu.buildBorder(cMenu);
	}
	
	var contextMenu = {
		buildTrigger:function(dom,op,id,selector){
			var cMenu = $.create('div','ccay-contextmenu',id),
				showpanel = $.create('div','ccay-contextmenu-hover').appendTo(cMenu);
			
			var trigger = $.create('div','ccay-contextmenu-trigger' + (op.setBorder ? '' : ' noborder'))
					.html('<a/>').appendTo(showpanel).click(function(e){
				//e.stopPropagation();
				var target = cMenu.data('target'),data;
				if(!target) return;
					
				data = op.fnGetData ? op.fnGetData(target) : null;

				if(!op.fnCallMenu || op.fnCallMenu(target,cMenu,selector,data) !== false){
					//自定义模式
					if(op.fnCustomMenu)
					{
						if(op.fnCustomMenu(target,selector,op,data,contextMenu))
							return false;
					}
					
					//动态创建模式
					if(op.fnDynamicMenu)
					{
						var menus = op.fnDynamicMenu(target,op,data);
						if(menus)
						{
							contextMenu.buildItems(selector,menus,op,true);
						}
					}
					else
						contextMenu.checkList(target,selector,op,data);
						
					var trigger = $(this).parent().parent(),
						fixed = {left:trigger.outerWidth() - selector.outerWidth(),top:trigger.outerHeight()};
					
					var position = trigger.fixedPosition();
					if(selector.outerHeight()+position.top+trigger.outerHeight()>dom[0].scrollTop+$(dom[0]).height()){
						fixed = {left:trigger.outerWidth() - selector.outerWidth(),top:-(selector.outerHeight()-1) };
					}
					
					op.setBorder || (fixed.top -= 1);
					Ccay.UI.popup(trigger,selector,fixed,true,op.offset);
				}
			});
		
			cMenu.appendTo(op.container || dom);

			// 是否buildBorder添加边框
			op.setBorder && contextMenu.buildBorder(cMenu);
			return cMenu;
		},
		callMenu:function(trigger,menu){
			var target = cMenu.data('target'),data = op.fnGetData ? op.fnGetData(target) : null;
		},
		buildList:function(dom,op,id){
			op._eList = {};
			op._checkFn = [];
			var selector = $.create('div','ccay-contextmenu-list',id+'_list').click(function(e){
				op.selectClose = true;
				var target = $.getEventTarget(e).parent(),ecode = target.attr("_ecode"),
					sel = $(this),trigger = $('#' + id);
				if(ecode)
				{
					var handler = op._eList[ecode];
					handler && handler(trigger.data("target"),target,op);
				}
				// 点击输入区不关闭
				if(target.hasClass("input-filter-div") || target.find("input").length > 0){
					op.selectClose = false;
				}
				op.selectClose !== false && contextMenu.close(trigger,sel,op);
			});
			
			this.buildItems(selector,op.menus,op).appendTo(op.container || dom);
			return selector;
		},
		buildItems:function(selector,menus,op,clear){
			if(clear)
			{
				selector.empty();
				op._eList = {};
				op._checkFn = [];
			}
			var html = [];
			this.addMenus(html,menus,op);
			return selector.html(html.join(""));
		},
		addMenus:function(html,menus,op){
			if(menus)
			{
				html.push(op.panelBegin);
				var click,children,itemHtml;
				$.each(menus,function(i,item){
	 				item.text && (item.text = "<a class='context-item'>" + $i18n(item.text) + "</a>");
	 				item.icon = item.icon || "noicon";
	 				item.children ? item.icon = "" : item.icon = "<a class='ccay-icon " + item.icon + "'></a>";
	 				
	 				if((children = item.children) && children.length)
					{
						item.parent ="parent";
						itemHtml = [];
						contextMenu.addMenus(itemHtml,children,op);
						item.children = itemHtml.join("");
					}
					//注册事件
					if(click = item.click)
					{	
		 				if(typeof(click) == "string")
		 					item.click = "onclick='" + click + "'";
			 			else{
			 				var no =$.newGuid('e_');
			 				op._eList[no] = click;
			 				item.click = "_ecode='" + no +"'";
			 			}
					}
					item.fnCheck && op._checkFn.push(item.fnCheck);
					html.push(op.item.formatField(item));
				});
		 		html.push(op.panelEnd);
			}
		},
		checkList:function(target,selector,op,data){
			selector.find('.ccay-contextmen-item').each(function(i){
				var menu = $(this),fnCheck = op._checkFn[i];
				(!fnCheck || fnCheck(target,menu,data)) ? menu.show() : menu.hide();
			});
		},
		close:function(cMenu,selector,op){
			var target = cMenu.data('target');
			if(target){
				target.removeData("cm_active").removeClass("ccay-contextmenu-active");
				cMenu.removeData('target');
			}
			cMenu.hide();
			selector.hide();
			op.setBorder && contextMenu.closeBorder(cMenu);
		},
		// 构造边框
		buildBorder:function(cMenu){
			var html = [];
			$.each(['left','top','bottom'],function(i,border){
				html.push("<div class='ccay-contextmenu-border",border,"' />")
			})
			cMenu.after(html.join(''));
		},
		// 边框效果
		popupBorder:function(target,op,cMenu){
			var width = target.outerWidth(),
				height = cMenu.outerHeight(),
				top = parseInt(cMenu.css('top')),
				left = parseInt(cMenu.css('left')) - width + cMenu.outerWidth(),
				leftBorder = cMenu.next().css({left:left,top:top,height:height}).show(),
				topBorder = leftBorder.next().css({left:left,top:top,width:width}).show();
			
			topBorder.next().css({left:left,top:top + height,width:width}).show();

		},
		// 关闭边框
		closeBorder:function(cMenu){
			cMenu.next().hide().next().hide().next().hide();
		}
	};
})();